package com.gae101.service;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.ServletException;

import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

public class ImageServiceImpl implements ImageService {

	private static final Logger log = Logger.getLogger(MailServiceImpl.class.getName());
	private MailService mailService = new MailServiceImpl();
	private GcmService gcmService = new GcmServiceImpl();
	
	private String imageEntityName = "UserImage";
	
	
	@Override
	public List<Entity> findAll(String userId) {
		/*
		Query query = new Query(imageEntityName).addSort("date", Query.SortDirection.DESCENDING);
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		List<Entity> images = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(15));
		return images;
		*/
		Filter userFilter = new FilterPredicate("userId", FilterOperator.EQUAL, userId);
		
		Query query = new Query(imageEntityName).addSort("date", Query.SortDirection.DESCENDING).setFilter(userFilter);
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		List<Entity> images = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(6));
		
		return images;
	}
	
	@Override
	public Entity last(String userId) {
		Filter userFilter = new FilterPredicate("userId", FilterOperator.EQUAL, userId);
		
		Query query = new Query(imageEntityName).addSort("date", Query.SortDirection.DESCENDING).setFilter(userFilter);
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		List<Entity> images = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(1));
		if (images.size() > 0) return images.get(0);
		else return null;
	}
	
	@Override
	public Entity get(Long id) {
		Key entryKey = KeyFactory.createKey(imageEntityName, id);
		
		Query query = new Query(imageEntityName).setFilter(new FilterPredicate(Entity.KEY_RESERVED_PROPERTY,
                Query.FilterOperator.EQUAL,
                entryKey));
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity image = datastore.prepare(query).asSingleEntity();
		return image;
	}
	
	// TODO userId check?
	@Override
	public void delete(Long id) {
		Entity image = get(id);
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		datastore.delete(image.getKey());
	}
	
	@Override
	public void save(String userId, byte[] rawImageData) {
		if (rawImageData == null || rawImageData.length <= 0) {
    		return;
    	}
    	            
        Blob image = new Blob(rawImageData);
		Date date = new Date();

		Entity imageEntity = new Entity(imageEntityName);
		imageEntity.setProperty("userId", userId);
		imageEntity.setProperty("image", image);
		imageEntity.setProperty("date", date);
		
		DatastoreService dataStoreService = DatastoreServiceFactory.getDatastoreService();
		Key key = dataStoreService.put(imageEntity);
		
		sendNotification(key);
	}
	
	protected void sendNotification(Key key) {
	
		User user = UserServiceFactory.getUserService().getCurrentUser();
		String userId = user.getUserId();
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Filter userFilter = new FilterPredicate("userId", FilterOperator.EQUAL, userId);
		Filter statusFilter  = new FilterPredicate("status", FilterOperator.EQUAL, "ON");
		
		Filter allFilter = CompositeFilterOperator.and(statusFilter, userFilter);
		Query query = new Query("UserDevice").setFilter(allFilter);
		List<Entity> devices = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(15));
		
		List<String> regIds = new ArrayList<String>();
		List<String> emails = new ArrayList<String>();
		for (Entity entity : devices) {
			String regId = (String) entity.getProperty("regId");
			if (regId != null && regId.length() > 0) {
				String type = (String) entity.getProperty("type");
				if (type.equals("VIEWER")) {
					regIds.add(regId);
					log.info("reg id " + regId);
				}
			}
			String email = (String) entity.getProperty("email");
			if (email != null && email.length() > 0) {
				emails.add(email);
			}
		}

		sendMessage(regIds);
		
		for (String email : emails) {
			log.info("send email : " + email);
			try {
				mailService.send(key.getId(), email);
			} catch (ServletException e) {
				log.info("failed to send email : " + email);
			}
		}
	}
	
	protected void sendmail(String userId, Key key) {
		try {
			mailService.send(key.getId(), "daclouds@gmail.com");
		} catch (Exception e) {
			log.warning(e.getMessage());
		}
	}
	
	protected void sendMessage(List<String> regIds) {
		DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
		Date now = Calendar.getInstance().getTime();
		String reportDate = df.format(now);

		try {
			gcmService.send("{\"type\":\"utility\",\"title\":\""+"a3cctv alert - "+ reportDate +"\",\"content\":\"somthing detected\"}", regIds);
		} catch (Exception e) {
			log.warning(e.getMessage());
		}
	}
	
}
